package com.example.travelgd.service;

import com.example.travelgd.entity.Specialty;
import com.example.travelgd.repository.SpecialtyMapper;
import com.example.travelgd.util.FwResult;
import com.example.travelgd.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SpecialtyService {

    @Autowired
    private SpecialtyMapper specialtyMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private WebSocketServer webSocketServer;

    private static final String SPECIALTY_CACHE_KEY = "travelgd:specialty";
    private static final long CACHE_EXPIRE_TIME = 5;
    private static final TimeUnit CACHE_EXPIRE_UNIT = TimeUnit.MINUTES;

    /**
     * 生成列表缓存key
     */
    private String generateListCacheKey(Integer categoryId) {
        return SPECIALTY_CACHE_KEY + ":list:" + (categoryId == null ? "all" : categoryId);
    }

    /**
     * 生成详情缓存key
     */
    private String generateDetailCacheKey(Long id) {
        return SPECIALTY_CACHE_KEY + ":detail:" + id;
    }

    /**
     * 获取特产列表
     */
    public List<Specialty> getSpecialtyList(Integer categoryId, Integer page, Integer pageSize) {
        // 构造缓存key
        String cacheKey = generateListCacheKey(categoryId);

        // 先从缓存获取
        List<Specialty> cachedList = (List<Specialty>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedList != null) {
            log.info("从缓存获取特产列表: {}", cachedList);
            return cachedList;
        }

        // 计算分页偏移量
        int offset = (page - 1) * pageSize;

        // 缓存未命中,从数据库查询
        List<Specialty> specialtyList;
        if (categoryId != null && categoryId != 0) {
            // 有分类过滤
            specialtyList = specialtyMapper.selectByCategoryWithPage(categoryId, offset, pageSize);
        } else {
            // 查询所有启用状态的特产
            specialtyList = specialtyMapper.selectAllEnabledWithPage(offset, pageSize);
        }
        log.info("从数据库获取特产列表: {}", specialtyList);

        // 放入缓存
        redisTemplate.opsForValue().set(cacheKey, specialtyList,
                CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);

        return specialtyList;
    }

    /**
     * 获取特产详情
     */
    public Specialty getSpecialtyDetail(Long id) {
        try {
            // 从缓存获取详情
            String cacheKey = generateDetailCacheKey(id);
            Specialty cachedSpecialty = (Specialty) redisTemplate.opsForValue().get(cacheKey);
            if (cachedSpecialty != null) {
                log.info("从缓存获取特产详情: {}", cachedSpecialty);
                return cachedSpecialty;
            }

            // 缓存未命中，从数据库查询
            Specialty specialty = specialtyMapper.selectById(id);
            if (specialty != null) {
                // 放入缓存
                redisTemplate.opsForValue().set(cacheKey, specialty,
                        CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);
                log.info("从数据库获取特产详情: {}", specialty);
            }
            return specialty;
        } catch (Exception e) {
            log.error("获取特产详情失败, id: {}", id, e);
            throw e;
        }
    }

    /**
     * 添加特产
     */
    public FwResult<Void> addSpecialty(Specialty specialty) {
        try {
            // 设置默认值
            specialty.setCreateTime(LocalDateTime.now());
            specialty.setUpdateTime(LocalDateTime.now());
            specialty.setStatus(specialty.getStatus() == null ? 1 : specialty.getStatus());
            specialty.setSales(specialty.getSales() == null ? 0 : specialty.getSales());


            if (specialtyMapper.insert(specialty) > 0) {
                // 清除缓存并重新加载
                refreshCache();
                // 推送更新消息
                webSocketServer.sendToAll("SPECIALTY_UPDATE");
                log.info("特产添加成功并推送更新消息，ID: {}", specialty.getId());
                return FwResult.ok();
            }
            return FwResult.failedMsg("添加特产失败");
        } catch (Exception e) {
            log.error("添加特产失败", e);
            return FwResult.failedMsg("添加特产失败");
        }
    }

    /**
     * 更新特产
     */
    public FwResult<Void> updateSpecialty(Specialty specialty) {
        try {
            specialty.setUpdateTime(LocalDateTime.now());
            if (specialtyMapper.updateById(specialty) > 0) {
                // 清除缓存
                clearCache();
                // 推送更新消息
                webSocketServer.sendToAll("SPECIALTY_UPDATE");
                log.info("特产更新成功并推送更新消息，ID: {}", specialty.getId());
                return FwResult.ok();
            }
            return FwResult.failedMsg("更新特产失败");
        } catch (Exception e) {
            log.error("更新特产失败", e);
            return FwResult.failedMsg("更新特产失败");
        }
    }

    /**
     * 删除特产
     */
    public FwResult<Void> deleteSpecialty(Long id) {
        try {
            if (specialtyMapper.deleteById(id) > 0) {
                // 清除缓存并重新加载
                refreshCache();
                // 推送更新消息
                webSocketServer.sendToAll("SPECIALTY_UPDATE");
                log.info("特产删除成功并推送更新消息，ID: {}", id);
                return FwResult.ok();
            }
            return FwResult.failedMsg("删除特产失败");
        } catch (Exception e) {
            log.error("删除特产失败", e);
            return FwResult.failedMsg("删除特产失败");
        }
    }

    /**
     * 清除所有特产相关缓存
     */
    public void clearCache() {
        try {
            String pattern = SPECIALTY_CACHE_KEY + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                log.info("清除特产缓存成功, keys: {}", keys);
            }
        } catch (Exception e) {
            log.error("清除特产缓存失败", e);
        }
    }

    /**
     * 刷新特产缓存
     */
    public void refreshCache() {
        try {
            // 获取所有分类
            List<Integer> categories = specialtyMapper.getAllCategories();

            // 清除所有相关缓存
            clearCache();

            // 为每个分类刷新缓存
            for (Integer categoryId : categories) {
                String cacheKey = generateListCacheKey(categoryId);
                List<Specialty> specialtyList = specialtyMapper.selectByCategory(categoryId);
                redisTemplate.opsForValue().set(cacheKey, specialtyList,
                        CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);
            }

            // 刷新全部列表缓存
            String allCacheKey = generateListCacheKey(null);
            List<Specialty> allSpecialtyList = specialtyMapper.selectAllEnabled();
            redisTemplate.opsForValue().set(allCacheKey, allSpecialtyList,
                    CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);

            log.info("刷新特产缓存成功");
            webSocketServer.sendToAll("SPECIALTY_UPDATE");
        } catch (Exception e) {
            log.error("刷新特产缓存失败", e);
        }
    }

    /**
     * 检查缓存是否有效
     */
    public boolean isCacheValid() {
        try {
            String pattern = SPECIALTY_CACHE_KEY + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            return keys != null && !keys.isEmpty();
        } catch (Exception e) {
            log.error("检查缓存状态失败", e);
            return false;
        }
    }
}